#!/bin/bash

# sdk_sync 一键部署脚本

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

# ========== 公共函数部分 ==========
# 等待端口监听
wait_for_port() {
    local port="$1"
    local timeout="$2"
    timeout=${timeout:-30}  # 默认30秒超时
    
    log_info "等待端口 ${port} 监听（超时: ${timeout}秒）..."
    
    local start_time=$(date +%s)
    local end_time=$((start_time + timeout))
    
    while [ $(date +%s) -lt $end_time ]; do
        if check_port_listening "$port"; then
            log_info "✓ 端口 ${port} 已监听"
            return 0
        fi
        
        # 显示等待进度
        local elapsed=$(( $(date +%s) - start_time ))
        echo -ne "等待中... ${elapsed}/${timeout}秒\r"
        sleep 2
    done
    
    log_warn "⚠ 端口 ${port} 在 ${timeout} 秒内未监听"
    return 1
}

# 检查端口监听状态
check_port_listening() {
    local port="$1"
    
    # 方法1: 使用netstat
    if command -v netstat &> /dev/null; then
        if netstat -tlnp 2>/dev/null | grep -q ":${port}"; then
            return 0
        fi
    fi
    
    # 方法2: 使用ss
    if command -v ss &> /dev/null; then
        if ss -tlnp 2>/dev/null | grep -q ":${port}"; then
            return 0
        fi
    fi
    
    # 方法3: 使用lsof
    if command -v lsof &> /dev/null; then
        if lsof -i :${port} >/dev/null 2>&1; then
            return 0
        fi
    fi
    
    return 1
}

# 安全停止服务
safe_stop_service() {
    log_info "安全停止现有服务..."
    
    # 检查并停止systemd服务
    if systemctl is-active --quiet sdk_sync 2>/dev/null; then
        log_info "停止systemd服务..."
        systemctl stop sdk_sync
        sleep 2
    fi
    
    # 检查并杀死相关进程
    if pgrep -f "sdk_sync" > /dev/null; then
        log_info "停止sdk_sync进程..."
        pkill -f "sdk_sync" || true
        sleep 2
        pkill -9 -f "sdk_sync" 2>/dev/null || true
    fi
}

# 完全清理服务
complete_cleanup() {
    log_info "开始完全清理..."
    
    # 1. 安全停止服务
    safe_stop_service
    
    # 2. 清理systemd服务配置
    if systemctl is-enabled --quiet sdk_sync 2>/dev/null; then
        log_info "禁用systemd服务..."
        systemctl disable sdk_sync
    fi
    
    if [ -f "/etc/systemd/system/sdk_sync.service" ]; then
        log_info "移除systemd服务文件..."
        rm -f /etc/systemd/system/sdk_sync.service
    fi
    
    # 3. 重新加载systemd
    systemctl daemon-reload
    systemctl reset-failed
    
    # 4. 删除程序目录
    if [ -d "/root/sdk_sync" ]; then
        log_info "删除程序目录 /root/sdk_sync..."
        rm -rf /root/sdk_sync
        log_info "✓ 程序目录已删除"
    else
        log_info "程序目录不存在，跳过删除"
    fi
    
    # 5. 清理备份文件
    # if ls /tmp/sdk_sync.service.backup.* 1> /dev/null 2>&1; then
    #     log_info "清理备份文件..."
    #     rm -f /tmp/sdk_sync.service.backup.*
    # fi
    
    log_info "✓ 完全清理完成"
}

# 检查sdk_sync目录是否存在
check_sdk_dir() {
    if [ ! -d "/root/sdk_sync" ]; then
        log_error "sdk_sync目录不存在，请先部署服务"
        return 1
    fi
    return 0
}

# 检查依赖环境
check_dependencies() {
    log_info "检查依赖环境..."
    
    if ! command -v docker &> /dev/null; then
        log_error "Docker未安装，请先安装Docker"
        log_info "运行: apt update && apt install -y docker.io"
        exit 1
    fi
    
    if ! docker ps | grep -q nats-server; then
        log_error "Nats 未安装，请先安装Nats"
        log_info "运行: docker run --network host -d --name nats-server -p 4222:4222  nats:latest"
        exit 1
    fi
}

# 下载必要文件
download_files() {
    local target_dir="$1"
    mkdir -p "$target_dir"
    cd "$target_dir"
    
    # 下载主程序
    if [ ! -f "sdk_sync" ]; then
        log_info "下载sdk_sync程序..."
        curl -o sdk_sync 'http://qq-sdk.oss-us-west-1.aliyuncs.com/xcpro/sdk_sync'
        chmod +x sdk_sync
    fi
    
    # 下载IP库文件
    mkdir -p conf
    cd conf
    
    if [ ! -f "ip4.dat" ]; then
        log_info "下载ip4.dat..."
        curl -o ip4.dat 'http://ipdatacloud-bin.oss-cn-hongkong.aliyuncs.com/ip4.dat'
    fi
    
    if [ ! -f "ip_scenes.dat" ]; then
        log_info "下载ip_scenes.dat..."
        curl -o ip_scenes.dat 'http://qq-sdk.oss-us-west-1.aliyuncs.com/xcpro/ip_scenes.dat'
    fi
    
    cd ..
}

# 创建配置文件
create_config() {
    local server_vendor="$1"
    local region="$2"
    local mark="$3"
    local redis_server="$4"
    local redis_password="$5"
    
    # 修复Redis配置：如果没有端口，添加默认端口
    if [ -n "$redis_server" ] && [[ ! "$redis_server" == *:* ]] && [[ ! "$redis_server" == "" ]]; then
        redis_server="$redis_server:6379"
    fi
    
    cd /root/sdk_sync/conf
    
    # 创建app.ini（如果不存在）
    if [ ! -f "app.ini" ]; then
        log_info "创建app.ini..."
        cat > app.ini << 'EOF'
[app]
RunMode = release
HttpPort = 7799
ReadTimeout = 10
WriteTimeout = 10
Name = sdk_sync
DisplayName = sdk_sync
Description = sdk设备同步模块
EOF
    fi
    
    # 创建sdk_sync.ini
    log_info "创建sdk_sync.ini..."
    cat > sdk_sync.ini << EOF
[module]
ServerVendor= $server_vendor
Region = $region
Mark= $mark

[database_ch]
RedisServer = $redis_server
RedisPassword = $redis_password

[mq]
MainNatsURL = sdk.nats.packetsdk.io
TunNatsURL = 127.0.0.1
EOF
    
    cd ..
}

# 安装并启动服务
install_and_start_service() {
    local target_dir="$1"
    cd "$target_dir"
    
    log_info "安装服务..."
    if ./sdk_sync install; then
        log_info "服务安装成功"
    else
        log_warn "服务安装返回警告，继续启动流程..."
    fi
    
    log_info "启动服务..."
    if ./sdk_sync start; then
        log_info "服务启动命令执行成功"
    else
        log_warn "服务启动命令返回警告，继续检查状态..."
    fi
    log_info "等待服务完全启动..."    
    sleep 5
}

# 显示服务状态
show_status() {
    echo
    log_info "=== 服务状态 ==="
    
    # 检查进程
    if pgrep -f "sdk_sync" > /dev/null; then
        log_info "✓ sdk_sync进程运行中"
        echo "进程信息:"
        ps aux | grep sdk_sync | grep -v grep | head -5
    else
        log_error "✗ sdk_sync进程未运行"
    fi
    
    # 检查端口（使用修复的检查方法）
    if check_port_listening 7799; then
        log_info "✓ 服务端口7799监听正常"
    else
        log_warn "⚠ 服务端口7799未监听"
        log_info "说明：服务可能正在启动中，请稍后再次检查"
        log_info "端口检查方法:"
        echo "  - netstat: $(command -v netstat 2>/dev/null || echo '未安装')"
        echo "  - ss: $(command -v ss 2>/dev/null || echo '未安装')"
        echo "  - lsof: $(command -v lsof 2>/dev/null || echo '未安装')"
    fi
    
    # 显示日志片段
    local log_file=$(find /root/sdk_sync -name "sdk_sync.*.log" -type f -printf "%T@ %p\n" 2>/dev/null | sort -n | tail -1 | cut -d' ' -f2-)
    
    if [ -n "$log_file" ] && [ -f "$log_file" ]; then
        echo
        log_info "最新日志片段:"
        tail -10 "$log_file" | while read line; do
            if echo "$line" | grep -q "ERRO"; then
                echo -e "${RED}$line${NC}"
            elif echo "$line" | grep -q "WARN"; then
                echo -e "${YELLOW}$line${NC}"
            else
                echo "$line"
            fi
        done
    else
        log_warn "未找到日志文件"
    fi
}

# 显示当前配置
show_current_config() {
    if [ -f "/root/sdk_sync/conf/sdk_sync.ini" ]; then
        echo
        log_info "当前配置文件:"
        echo "=========================================="
        cat /root/sdk_sync/conf/sdk_sync.ini
        echo "=========================================="
    else
        log_warn "未找到配置文件"
    fi
}

# 配置参数输入
get_config() {
    echo
    log_info "请配置sdk_sync参数"
    echo "=========================================="
    
    # ServerVendor配置
    echo "可选服务器供应商:"
    echo "1) tencent  2) huawei  3) ali  4) ucloud"
    echo "5) huoshan  6) zenlayer 7) ocean 8) oracle 9) test"
    read -p "请选择服务器供应商编号 (1-9, 默认9): " vendor_choice
    
    case $vendor_choice in
        1) ServerVendor="tencent" ;;
        2) ServerVendor="huawei" ;;
        3) ServerVendor="ali" ;;
        4) ServerVendor="ucloud" ;;
        5) ServerVendor="huoshan" ;;
        6) ServerVendor="zenlayer" ;;
        7) ServerVendor="ocean" ;;
        8) ServerVendor="oracle" ;;
        9|"") ServerVendor="test" ;;
        *) ServerVendor="test" ;;
    esac
    
    # Region配置
    echo "可选区域:"
    echo "1) na  2) as  3) eu  4) va"
    read -p "请选择区域编号 (1-4, 默认3): " region_choice
    
    case $region_choice in
        1) Region="na" ;;
        2) Region="as" ;;
        3|"") Region="eu" ;;
        4) Region="va" ;;
        *) Region="eu" ;;
    esac
    
    # Mark配置
    read -p "请输入集群标记 [默认: universal]: " Mark
    Mark=${Mark:-universal}
    
    # Redis配置
    echo
    read -p "是否配置Redis? [y/N]: " config_redis
    if [[ $config_redis =~ ^[Yy]$ ]]; then
        read -p "Redis服务器地址 [例如: 127.0.0.1:6379]: " RedisServer
        read -p "Redis密码: " RedisPassword
    else
        RedisServer=""
        RedisPassword=""
    fi
}

# ========== 部署功能部分 ==========

# 快速部署
quick_deploy() {
    log_info "开始快速部署..."
    
    mkdir -p /root/sdk_sync
    download_files "/root/sdk_sync"
    create_config "test" "eu" "universal" "127.0.0.1:6379" "123456"
    install_and_start_service "/root/sdk_sync"
}

# 交互式部署
interactive_deploy() {
    log_info "开始交互式部署..."
    get_config
    
    mkdir -p /root/sdk_sync
    download_files "/root/sdk_sync"
    create_config "$ServerVendor" "$Region" "$Mark" "$RedisServer" "$RedisPassword"
    install_and_start_service "/root/sdk_sync"
}

# 重启服务
restart_service() {
    log_info "重启服务..."
    
    if ! check_sdk_dir; then
        return 1
    fi
    
    cd /root/sdk_sync
    
    if [ ! -f "sdk_sync" ]; then
        log_error "sdk_sync程序不存在"
        return 1
    fi
    
    safe_stop_service
    ./sdk_sync start
    wait_for_port 7799 15
    return 0
}

# ========== 主菜单和入口 ==========

# 主菜单
main_menu() {
    while true; do
        echo
        log_info "SDK资源同步中台部署脚本"
        echo "========================================"
        echo "1. 快速部署（使用默认配置，请先修改quick_deploy配置）"
        echo "2. 交互式部署（可选择配置）"
        echo "3. 重启服务"
        echo "4. 清理服务"
        echo "5. 查看状态"
        echo "6. 查看配置"
        echo "7. 退出"
        echo
        
        read -p "请选择操作 (1-7): " choice
        
        # 处理空输入
        if [ -z "$choice" ]; then
            log_error "请输入有效数字"
            continue
        fi
        
        case $choice in
            1)
                check_dependencies
                quick_deploy
                show_status
                ;;
            2)
                check_dependencies
                interactive_deploy
                show_status
                ;;
            3)
                if restart_service; then    
                    show_status
                fi
                ;;
            4)
                complete_cleanup
                ;;            
            5)
                if check_sdk_dir; then
                    show_status
                fi
                ;;
            6)
                if check_sdk_dir; then
                    show_current_config
                fi
                ;;
            7)
                log_info "退出脚本"
                exit 0
                ;;
            *)
                log_error "无效选择"
                ;;
        esac
        
        echo
        read -p "按回车键继续..." dummy
    done
}

# 脚本入口
if [ "$1" = "auto" ]; then
    quick_deploy
    show_status
elif [ "$1" = "clean" ]; then
    complete_cleanup
elif [ "$1" = "status" ]; then
    show_status
else
    main_menu
fi